home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWrap / Source / TGIF.m < prev    next >
Text File  |  1991-09-18  |  11KB  |  450 lines

  1. #import "TGIF.h"
  2. #import "ListCell.h"
  3. #import "ListMatrix.h"
  4. #import "NXBitmapGraphicRep.h"
  5. #import "PolyInspector.h"
  6. #import "TGIFCell.h"
  7. #import "miscutil.h"
  8. #import <appkit/Application.h>
  9. #import <appkit/Matrix.h>
  10. #import <appkit/NXCursor.h>
  11. #import <appkit/OpenPanel.h>
  12. #import <appkit/SavePanel.h>
  13. #import <appkit/ScrollView.h>
  14. #import <appkit/Window.h>
  15. #import <appkit/color.h>
  16. #import <appkit/graphics.h>
  17. #import <appkit/nextstd.h>
  18. #import <stdio.h>
  19. #import <streams/streams.h>
  20. #import <sys/param.h>
  21.  
  22. // import command cell objects
  23. #import "CmdBgcolor.h"
  24. #import "CmdBgnpoly.h"
  25. #import "CmdCircle.h"
  26. #import "CmdComment.h"
  27. #import "CmdDraw.h"
  28. #import "CmdEndpoly.h"
  29. #import "CmdFgcolor.h"
  30. #import "CmdFps.h"
  31. #import "CmdHold.h"
  32. #import "CmdMove.h"
  33. #import "CmdNewframe.h"
  34. #import "CmdVertex.h"
  35.  
  36. #import "AbsPoly.h"
  37.  
  38. NXBitmapGraphicRep *theBitmap=nil;
  39.  
  40. @implementation TGIF
  41. id backup;  // for undo
  42. id openPanel, savePanel;
  43. id pbList;  // for a "pasteboard" of cells.
  44.  
  45. BOOL getOpenPath(char *buf, char const *type1, char const *type2)
  46. {
  47.   char const *fileTypes[3] = {0,0,0};
  48.   
  49.   if (!openPanel)
  50.       openPanel = [OpenPanel new];
  51.   [openPanel allowMultipleFiles:NO];
  52.   if (type1 && *type1)
  53.       fileTypes[0] = type1;
  54.   if (type2 && *type2)
  55.       fileTypes[1] = type2;
  56.   [NXApp setAutoupdate:NO];
  57.   if ([openPanel runModalForDirectory:(const char*)buf
  58.    file:"" types:fileTypes]) {
  59.     strcpy(buf,[openPanel filename]);
  60.     [NXApp setAutoupdate:YES];
  61.     return YES;
  62.   } else {
  63.     [NXApp setAutoupdate:YES];
  64.     return NO;
  65.   }
  66. }
  67.  
  68. BOOL getSavePath(char *returnBuf, char *dir, char *name, char const *theType)
  69. {
  70.   if (!savePanel) {
  71.     savePanel = [SavePanel new];
  72.    [savePanel setTitle:"GraphicsWrap Save"];
  73.   }
  74.   if (theType && *theType)
  75.       [savePanel setRequiredFileType:theType];
  76.   [NXApp setAutoupdate:NO];
  77.   if ([savePanel runModalForDirectory:dir file:name]) {
  78.     strcpy(returnBuf,[savePanel filename]);
  79.     [NXApp setAutoupdate:YES];
  80.     return YES;
  81.   } else {
  82.     [NXApp setAutoupdate:YES];
  83.     return NO;
  84.   }
  85. }
  86.  
  87. void parsePath(char *path, char *dir, char *name)
  88. {
  89.   char *c1, *c2;
  90.   int dirlen, namelen;
  91.   
  92.   c1 = strrchr(path, '.');
  93.   c2 = strrchr(path, '/');
  94.   dirlen = (c2) ? c2-path+1 : 0;
  95.   namelen = ((c1) ? c1-path : strlen(path)) -dirlen;
  96.   strncpy(dir,path,dirlen);
  97.   dir[dirlen] = '\0';
  98.   strncpy(name, path+dirlen, namelen);
  99.   name[namelen] = '\0';
  100. }
  101.  
  102. void getPath(char *path, char *dir, char *name, char *ext)
  103.      /* construct a path given a file name, directory, and type */
  104. {
  105.   strcpy(path,(dir)?dir:NXHomeDirectory());
  106.   if (name) {
  107.     strcat(path,name);
  108.     if (strlen(ext) && (ext[0] != '.'))
  109.     strcat(path,".");
  110.     strcat(path,ext);
  111.   }
  112. }
  113.  
  114. - displayMatrix:aMatrix
  115. {
  116.   [aMatrix sizeToCells];
  117.   [aMatrix display];
  118.   return self;
  119. }
  120.  
  121. - initMatrix
  122. {
  123.   NXRect aRect, bRect;
  124.   NXSize cellSpacing={0.0,0.0}, cellSize;
  125.   
  126.   [tgif_view getFrame:&aRect];
  127.   [ScrollView getContentSize:&(bRect.size) forFrameSize:&(aRect.size)
  128.    horizScroller:YES vertScroller:YES borderType:NX_BEZEL];
  129.   
  130.   tgif_matrix = [[ListMatrix alloc] initFrame:&bRect mode:NX_LISTMODE
  131.            cellClass:[TGIFCell class] numRows:0 numCols:1];
  132.   [tgif_matrix setIntercell:&cellSpacing];
  133.   [tgif_matrix allowEmptySel:YES];
  134.   [tgif_matrix setControlDrag:YES];
  135.   
  136.   [tgif_matrix getCellSize:&cellSize];
  137.   cellSize.width = NX_WIDTH(&bRect);
  138.   [tgif_matrix setCellSize:&cellSize];
  139.   [tgif_matrix sizeToCells];
  140.   [tgif_matrix setAutosizeCells:YES];
  141.   [tgif_matrix setAutoscroll:YES];
  142.   
  143.   [tgif_view setDocView:tgif_matrix];
  144.   [[tgif_matrix superview] setAutoresizeSubviews:YES];
  145.   [tgif_matrix setAutosizing:NX_WIDTHSIZABLE];
  146.   
  147.   [tgif_matrix setBackgroundGray:NX_LTGRAY];
  148.   [tgif_matrix setCellBackgroundGray:NX_LTGRAY];
  149.   [tgif_view setBackgroundGray:NX_LTGRAY];
  150.   
  151.   [tgif_view setDocCursor:NXArrow];
  152.   [tgif_matrix setTarget:self];
  153.   [tgif_matrix setAction:@selector(tgif_click:)];
  154.   [self displayMatrix:tgif_matrix];
  155.   return self;
  156. }
  157.  
  158. - initWithBitmap:abp andView:av;
  159. {
  160.   char title[100];
  161.   [super init];
  162.   [NXApp loadNibSection:"TGIF.nib" owner:self withNames:NO];
  163.   theBitmap=abp;
  164.   bitmap_view=av;
  165.  
  166.   poly_insp=[[PolyInspector alloc] init];
  167.  
  168.   NX_MALLOC(filePath,char,MAXPATHLEN+1);
  169.   NX_MALLOC(fileName,char,MAXPATHLEN+1);
  170.   NX_MALLOC(fileDir,char,MAXPATHLEN+1);
  171.  
  172.   sprintf(title,"UNTITLED.tgif");
  173.   [tgif_window setTitleAsFilename:(const char*)title];
  174.   NXPing();
  175.   
  176.   sprintf(filePath,"~/");
  177.   sprintf(fileName,title);
  178.   sprintf(fileDir,"~/");
  179.  
  180.   [self initMatrix];
  181.  
  182.   return self;
  183. }
  184.  
  185.  
  186. - perform:sender
  187. {
  188.   id cellList=[tgif_matrix cellListIncludeAll:NO];
  189.   int i, max=[cellList count];
  190.  
  191.   if(!max)cellList=[tgif_matrix cellListIncludeAll:YES];
  192.   for(i=0;i<max;i++){
  193.     [[cellList objectAt:i] doCmd];
  194.     [bitmap_view display];
  195.   }
  196.   return self;
  197. }
  198.  
  199. - tgif_click:sender
  200. {
  201.   id tList=[tgif_matrix cellListIncludeAll:NO];
  202.   
  203.   if(([tList count] == 1) && [[tList objectAt:0] isMemberOf:[AbsPoly class]]){
  204.     [poly_insp inspect:[tList objectAt:0]];
  205.     [[poly_insp window] makeKeyAndOrderFront:self];
  206.   } else [[poly_insp window] orderOut:self];
  207.   return self;
  208. }
  209.  
  210. - saveToFile
  211. {
  212.   int i;
  213.   id cmdList;
  214.   NXStream *theStream;
  215.   
  216.   if (!getSavePath(filePath,fileDir,fileName,"tgif"))
  217.       return self;
  218.   parsePath(filePath, fileDir, fileName);
  219.   theStream=NXOpenMemory(NULL, 0, NX_WRITEONLY);
  220.   cmdList=[tgif_matrix cellListIncludeAll:YES];
  221.   for(i=0;i<[cmdList count];i++)
  222.     NXPrintf(theStream, "%s", [[cmdList objectAt:i] emitCmd]);
  223.   NXFlush(theStream);
  224.   NXSaveToFile(theStream, filePath);
  225.   NXClose(theStream);
  226.   return self;
  227. }
  228.  
  229. - addRowTo:newCell
  230. {
  231.   int rc, cc;
  232.   [tgif_matrix getNumRows:&rc numCols:&cc];
  233.   [tgif_matrix addRow];
  234.   [tgif_matrix putCell:newCell at:rc :0];  
  235.   return self;
  236. }
  237.  
  238. id curPoly;
  239. BOOL polyMode;
  240. - addActiveCmd:(char *)cmd
  241. {
  242.   long arg1=-1, arg2=-1, arg3=-1;
  243.   int cc=0, argnum=0;
  244.   char *c[3];
  245.  
  246.   c[0]=c[1]=c[2]=(char *)nil;
  247.   while(cmd[cc]!='\0'){
  248.     if(cmd[cc]==' '){
  249.       cmd[cc]='\0';
  250.       c[argnum++]=&cmd[++cc];
  251.     } else cc++;
  252.   }
  253.  
  254.   if(c[0]) arg1=atol(c[0]);
  255.   if(c[1]) arg2=atol(c[1]);
  256.   if(c[2]) arg3=atol(c[2]);
  257.  
  258.   if (polyMode){
  259.     // check for "endpoly"
  260.     if(!strcmp(cmd, "endpoly") || !strcmp(cmd,"ep")){
  261.       [curPoly addCommand:[[CmdEndpoly alloc] initCmd]];
  262.       polyMode=FALSE;
  263.     }
  264.     //check for "vertex"
  265.     else if(!strcmp(cmd, "vertex") || !strcmp(cmd,"v"))
  266.       [curPoly addCommand:[[CmdVertex alloc] initCmd:arg1 :arg2]];
  267.     else fprintf(stderr, "Illegal token in PolyGon definition:%s %d %d %d\n",
  268.          cmd, arg1, arg2, arg3);
  269.   } else {  
  270.     // check for "move"
  271.     if(!strcmp(cmd, "move") || !strcmp(cmd,"m"))
  272.       [self addRowTo:[[CmdMove alloc] initCmd:arg1 :arg2]];
  273.     // check for "draw"
  274.     else if(!strcmp(cmd, "draw") || !strcmp(cmd,"d"))
  275.       [self addRowTo:[[CmdDraw alloc] initCmd:arg1 :arg2]];
  276.     // check for "circle"
  277.     else if(!strcmp(cmd, "circle") || !strcmp(cmd,"c"))
  278.       [self addRowTo:[[CmdCircle alloc] initCmd:arg1]];
  279.     //check for "fgcolor"
  280.     else if(!strcmp(cmd, "fgcolor") || !strcmp(cmd,"fg"))
  281.       [self addRowTo:[[CmdFgcolor alloc] initCmd:arg1 :arg2 :arg3]];
  282.     // check for "bgcolor"
  283.     else if(!strcmp(cmd, "bgcolor") || !strcmp(cmd,"bg"))
  284.       [self addRowTo:[[CmdBgcolor alloc] initCmd:arg1 :arg2 :arg3]];
  285.     // check for "bgnpoly"
  286.     else if(!strcmp(cmd, "bgnpoly") || !strcmp(cmd,"bp")){
  287.       curPoly=[[AbsPoly alloc] init];
  288.       [self addRowTo:curPoly];
  289.       [curPoly addCommand:[[CmdBgnpoly alloc] initCmd]];
  290.       polyMode=TRUE;
  291.     }
  292.     // check for "newframe"
  293.     else if(!strcmp(cmd, "newframe") || !strcmp(cmd,"n"))
  294.       [self addRowTo:[[CmdNewframe alloc] initCmd]];
  295.     // check for "fps"
  296.     else if(!strcmp(cmd, "fps"))
  297.       [self addRowTo:[[CmdFps alloc] initCmd:arg1]];
  298.     // check for "hold"
  299.     else if(!strcmp(cmd, "hold"))
  300.       [self addRowTo:[[CmdHold alloc] initCmd:arg1]];
  301.     else fprintf(stderr, "Bad Token (ignore -1): %s %d %d %d\n",
  302.          cmd, arg1, arg2, arg3);
  303.   }
  304.   
  305.   return self;
  306. }
  307.  
  308. - openFile
  309. {
  310.   char path[MAXPATHLEN+1], cmd[2000];
  311.   char c;
  312.   int rc, cc;
  313.   NXStream *theStream;
  314.   if (getOpenPath(path,"tgif",fileDir)) {
  315.     [tgif_matrix getNumRows:&rc numCols:&cc];
  316.     for(cc=0;cc<rc;cc++)
  317.       [tgif_matrix removeRowAt:cc andFree:YES];
  318.     theStream=NXMapFile(path, NX_READONLY);
  319.  
  320.     cc=0;
  321.     while((c=NXGetc(theStream))!=EOF){
  322.       cmd[cc]=c;
  323.       if(c=='\n'){
  324.     cmd[cc]='\0';
  325.     cc=0;
  326.     if(cmd[0]=='#') {
  327.       // this is a comment line
  328.       [self addRowTo:[[CmdComment alloc] initComment:cmd]];
  329.     } else
  330.       // this is really a command, process it as one
  331.       [self addActiveCmd:cmd];
  332.       } else cc++;
  333.     }
  334.     NXClose(theStream);
  335.   }
  336.   [self displayMatrix:tgif_matrix];
  337.   strcpy(filePath, path);
  338.   parsePath(filePath, fileDir, fileName);
  339.   [tgif_window setTitleAsFilename:(const char*)filePath];
  340.   return self;
  341. }
  342.  
  343. - newFile
  344. {
  345.   char title[100];
  346.   int i, rc, cc;
  347.   [tgif_matrix getNumRows:&rc numCols:&cc];
  348.   for(i=0;i<rc;i++)
  349.     [tgif_matrix removeRowAt:0 andFree:YES];
  350.   [self displayMatrix:tgif_matrix];
  351.   
  352.   sprintf(title,"UNTITLED.tgif");
  353.   [tgif_window setTitleAsFilename:(const char*)title];
  354.   NXPing();
  355.   
  356.   sprintf(filePath,"~/");
  357.   sprintf(fileName,title);
  358.   sprintf(fileDir,"~/");
  359.   return self;
  360. }
  361.  
  362.  
  363. - cmdMove:(int)x :(int)y
  364. {
  365.   [self addRowTo:[[CmdMove alloc] initCmd:x :y]];
  366.   [self displayMatrix:tgif_matrix];
  367.   return self;
  368. }
  369.  
  370. - cmdDraw:(int)x :(int)y
  371. {
  372.   [self addRowTo:[[CmdDraw alloc] initCmd:x :y]];
  373.   [self displayMatrix:tgif_matrix];
  374.   return self;
  375. }
  376.  
  377. -cmdNewFrame
  378. {
  379.   [self addRowTo:[[CmdNewframe alloc] initCmd]];
  380.   [self displayMatrix:tgif_matrix];
  381.   return self;
  382. }
  383.  
  384. - cmdForeColor:(NXColor)aColor
  385. {
  386.   [self addRowTo:[[CmdFgcolor alloc] initCmdColor:aColor]];
  387.   [self displayMatrix:tgif_matrix];
  388.   return self;
  389. }
  390.  
  391. - cmdBackColor:(NXColor)aColor
  392. {
  393.   [self addRowTo:[[CmdBgcolor alloc] initCmdColor:aColor]];
  394.   [self displayMatrix:tgif_matrix];
  395.   return self;
  396. }
  397.  
  398.  
  399. - cmdComment:(char *)comment
  400. {
  401.   char *tmp;
  402.   tmp=(char *) malloc((strlen(comment)+3)*sizeof(char));
  403.   sprintf(tmp, "#%s\n", comment);
  404.   [self addRowTo:[[CmdComment alloc] initComment:tmp]];
  405.   free(tmp);
  406.   return self;
  407. }
  408.  
  409. - cmdNewPoly
  410. {
  411.   // create new polygon
  412.   id aPoly=[[AbsPoly alloc] init];
  413.  
  414.   // add polygon to our matrix
  415.   [self addRowTo:aPoly];
  416.   [self displayMatrix:tgif_matrix];
  417.   
  418.   // return polygon to caller for vertex addition
  419.   return aPoly;
  420. }
  421.  
  422. // through first responder
  423. - delete:sender
  424. {
  425.   id cellList;
  426.   int i, rc, cc;
  427.   cellList=[tgif_matrix cellListIncludeAll:NO];
  428.   for(i=0;i<[cellList count];i++){
  429.     [tgif_matrix getRow:&rc andCol:&cc ofCell:[cellList objectAt:i]];
  430.     [tgif_matrix removeRowAt:rc andFree:NO];
  431.   }
  432.   [cellList freeObjects];
  433.   [self displayMatrix:tgif_matrix];
  434.   return self;
  435. }
  436.  
  437. - cut:sender
  438. {
  439.   int i, rc, cc;
  440.   if(pbList) [pbList free]; else pbList=[[List alloc] init];
  441.   pbList=[tgif_matrix cellListIncludeAll:NO];
  442.   for(i=0;i<[pbList count];i++){
  443.     [tgif_matrix getRow:&rc andCol:&cc ofCell:[[pbList objectAt:i] copy]];
  444.     [tgif_matrix removeRowAt:rc andFree:YES];
  445.   }
  446.   [self displayMatrix:tgif_matrix];
  447.   return self;
  448. }
  449. @end
  450.